NOTE: if you have not yet installed this OSAX, then do it before starting this lesson. The script will not compile without it. Go back to the Requirements section to download the OSAX if you need it.
property crlf : (ASCII character 13) & (ASCII character 10) property http_10_header : "HTTP/1.0 200 OK" & crlf & "Server: WebSTAR/1.0 ID/ACGI" & crlf & ¬ "MIME-Version: 1.0" & crlf & "Content-type: text/html" & crlf & crlf property idletime : 1800 property datestamp : 0 set datestamp to current date on «event WWWΩsdoc» path_args ¬ given «class kfor»:http_search_args, «class post»:post_args, «class meth»:method, « class addr»:client_address, «class user»:username, «class pass»:password, «class frmu»:from_user, « class svnm»:server_name, «class svpt»:server_port, «class scnm»:script_name, « class ctyp»:content_type, «class refr»:referer, «class Agnt»:user_agent, « class Kact»:action, «class Kapt»:action_path, «class Kcip»:client_ip, «class Kfrq»:full_request set datestamp to current date set return_page to http_10_header ¬ & "<HTML><HEAD><TITLE>Unprocessed Results</TITLE></HEAD>" ¬ & "<BODY><H1>Unprocessed Results</H1>" & return ¬ & "<H4>path_args</H4>" & return & path_args & return ¬ & "<H4>http_search_args</H4>" & return & http_search_args set return_page to return_page & return ¬ & "<H4>post_args</H4>" & return & post_args & return ¬ & "<H4>method</H4>" & return & method & return ¬ & "<H4>client_address</H4>" & return & client_address & return ¬ & "<H4>username</H4>" & return & username & return ¬ & "<H4>password</H4>" & return & password & return set return_page to return_page & return ¬ & "<H4>from_user</H4>" & return & from_user & return ¬ & "<H4>server_name</H4>" & return & server_name & return ¬ & "<H4>server_port</H4>" & return & server_port & return ¬ & "<H4>script_name</H4>" & return & script_name & return ¬ & "<H4>content_type</H4>" & return & content_type & return ¬ & "<H4>referer</H4>" & return & referer & return set return_page to return_page & return ¬ & "<H4>user_agent</H4>" & return & user_agent & return ¬ & "<H4>action</H4>" & return & action & return ¬ & "<H4>action_path</H4>" & return & action_path & return ¬ & "<H4>client_ip</H4>" & return & client_ip & return ¬ & "<H4>full_request</H4>" & return & full_request & return set return_page to return_page ¬ & "<I>Results generated at: " & (current date) ¬ & "</I>" & "</BODY></HTML>" return return_page end «event WWWΩsdoc» on idle if (current date) > (datestamp + idletime) then quit end if return 5 end idle on quit continue quit end quit
property idletime : 1800 property datestamp : 0These are two new properties that are used to control when the CGI will quit itself. idletime tells how long to allow the CGI to remain idle before quitting. It is measured in seconds, so the line above lets the CGI run 30 minutes before quitting. datestamp contains the last date that something happened. As you will see below, it is set at startup and at the start of each Apple event. It is important that these are properties, so their value persists between Apple events received.
set datestamp to current dateThis line gets the current date (which includes day and time) and stores it in the variable datestamp. This line is used twice; once at the very start and once inside the Apple event handler. By putting it outside the Apple event handler, it ensures that the CGI will quit as desired even if it was somehow launched without an Apple event. The line inside the Apple event handler ensures that it will be reset each time an Apple event is processed.
on idle if (current date) > (datestamp + idletime) then quit end if return 5 end idleThis new handler is introduced to test whether it is time to quit or not. When "nothing" is happening (meaning, when no Apple events are sent to this CGI), an "idle" event is sent to the CGI. The idle handler checks the current time and compares it to the last set time to see if it has been long enough to quit yet. If so, then it calls the quit handler (see below). If not, then it returns a value that tells how long to wait before checking for idle again (you don't want to tie up the whole cpu checking to see if you're idle!).
on quit continue quit end quitThis new handler allows you to do processing before quitting. This might be useful if you wanted to save some information about the current state, wanted to log when the CGI runs, or anything else you can think of. Logging could be very useful to get an idea of whether your idletime is set too high or too low for the use the CGI is getting. Currently all this does is tell the CGI to go ahead and quit.
I haven't mentioned yet why you might want to have your script quit. Well, there are a couple of good reasons. One is if you are developing a CGI. Having it quit after a couple of minutes is a good way to make sure that you will be able to overwrite it with an updated version as you make changes. Another reason is for memory management. If your server doesn't have enough memory to keep all of your CGI's running at once (and you don't want to spring for more memory) then this method keeps only those CGI's that are needed in memory. A final reason is "just because you want to." I don't like having 15 or 20 CGI's open all of the time when the majority of them are only used once a day or so. For those that are rarely used, I have them quite between runs.
Now there is the other question: Why not have your CGI's quit? Well, your users will get a much better response from a CGI that is already open and ready to run than from one that has to launch itself first. On some systems that delay may amount to several seconds. In most cases you want to give your user the best performance possible. There is also a possible problem with lost requests. When your CGI quits, there is a period where it is in the process of quitting. During this period it can still receive requests from WebSTAR, but it can't respond to them because it is busy quitting. These requests will be lost if this occurs. Your CGI will take longer to quit if you have any extra commands in the quit handler, or if you have properties that have changed (they have to be saved to disk). The longer it takes to quit, the more likely you are to miss a request. I have set these scripts to quit after 30 minutes. Since it only takes about 3 seconds to quit, that means the odds are pretty low that a request will come right at that moment. The longer you keep the CGI running, the lower the odds are that you will lose a request.
Also, some people are afraid that all that starting and quitting will cause memory fragmentation - that means that your memory is allocated in chunks that are not contiguous, so that your free memory is not available in one large block. This is not the same as disk fragementation. It will not make your computer run any more slowly. In addition, since most CGI's written in AppleScript tend to use the same amount of memory (about 200K), they will be able to fit in the slot they or another CGI left behind. In other words, I don't think this is a worry.
There is one caveat when working with scripts that are self-quitting. You want to be careful not to quit the script before you are done processing all of the Apple events that might be queued up. This is not a problem with regular CGI applications. With the new ability to do asynchronous processing of CGI applications, though, there is the possibility for this to be a problem. For that reason, make sure that idletime is long enough for the Apple event to be processed and another one that is waiting to be accepted.
Jon Wiederspan
Last Edited: April 26, 1995
Copyright Jon Wiederspan, 1994,1995